package com.atguigu.gmall.activity.service.impl;

import com.atguigu.gmall.activity.mapper.SeckillGoodsMapper;
import com.atguigu.gmall.activity.service.SeckillGoodsService;
import com.atguigu.gmall.activity.util.CacheHelper;
import com.atguigu.gmall.common.constant.MqConst;
import com.atguigu.gmall.common.constant.RedisConst;
import com.atguigu.gmall.common.result.Result;
import com.atguigu.gmall.common.result.ResultCodeEnum;
import com.atguigu.gmall.common.service.RabbitService;
import com.atguigu.gmall.common.util.MD5;
import com.atguigu.gmall.model.activity.OrderRecode;
import com.atguigu.gmall.model.activity.SeckillGoods;
import com.rabbitmq.client.Return;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.concurrent.TimeUnit;

@Service
public class SeckillGoodsServiceImpl implements SeckillGoodsService {

    @Autowired
    RedisTemplate redisTemplate;

    @Autowired
    SeckillGoodsMapper seckillGoodsMapper;

    @Autowired
    RabbitService rabbitService;

    @Override
    public List<SeckillGoods> findAll() {
        return redisTemplate.boundHashOps(RedisConst.SECKILL_GOODS).values();

    }

    @Override
    public SeckillGoods getSeckillGoods(Long skuId) {
        SeckillGoods seckillGoods  = (SeckillGoods) redisTemplate.boundHashOps(RedisConst.SECKILL_GOODS).get(skuId.toString());
        return seckillGoods;
    }

    //预下单业务逻辑
    @Override
    public void seckillOrder(Long skuId, String userId) {
        //产品状态位， 1：可以秒杀 0：秒杀结束
        String stuts = (String) CacheHelper.get(skuId.toString());
        if(StringUtils.isEmpty(stuts) || "0".equals(stuts)){
            return;
        }
        //判断用户是否已下单
        Boolean exist = redisTemplate.opsForValue().setIfAbsent(RedisConst.SECKILL_USER + userId, skuId,RedisConst.SECKILL__TIMEOUT,TimeUnit.SECONDS );
        if(!exist){
            return;
        }
        //获取队列中的商品，如果能够获取，则商品存在，可以下单
        String goodsId = (String) redisTemplate.boundListOps(RedisConst.SECKILL_STOCK_PREFIX + skuId).rightPop();
        if(StringUtils.isEmpty(goodsId)){
            redisTemplate.convertAndSend("seckillpush",skuId+":0");
            //已售罄
            return;
        }
        //订单记录
        OrderRecode orderRecode = new OrderRecode();
        orderRecode.setUserId(userId);
        orderRecode.setSeckillGoods(this.getSeckillGoods(skuId));
        orderRecode.setNum(1);
        //生成订单码
        orderRecode.setOrderStr(MD5.encrypt(userId+skuId));
        //订单数据存入Reids
        redisTemplate.boundHashOps(RedisConst.SECKILL_ORDERS).put(orderRecode.getUserId(),orderRecode);
        //跟新库存
        this.rabbitService.sendMessage(MqConst.EXCHANGE_DIRECT_SECKILL_STOCK,MqConst.ROUTING_SECKILL_USER,skuId);
    }

    @Override
    public void seckillStock(Long skuId) {

        String redisKey = RedisConst.SECKILL_STOCK_PREFIX+skuId;

        Long redisCount = redisTemplate.boundListOps(redisKey).size();
        SeckillGoods seckillGoods = this.getSeckillGoods(skuId);
        seckillGoods.setStockCount(redisCount.intValue());
        seckillGoodsMapper.updateById(seckillGoods);

        redisTemplate.boundHashOps(RedisConst.SECKILL_GOODS).put(seckillGoods.getSkuId().toString(),seckillGoods);
    }

    @Override
    public Result checkOrder(String userId, Long skuId) {
        Boolean isExist = redisTemplate.hasKey(RedisConst.SECKILL_USER + userId);
        if(isExist){
            //判断是否正在排队
            //判断用户是否下单
            Boolean exist = this.redisTemplate.opsForHash().hasKey(RedisConst.SECKILL_ORDERS, userId);
            if(exist){
                OrderRecode orderRecode = (OrderRecode) this.redisTemplate.opsForHash().get(RedisConst.SECKILL_ORDERS, userId);
                //秒杀成功
                return Result.build(orderRecode, ResultCodeEnum.SECKILL_SUCCESS);
            }
        }
        //判断是否下单

        Boolean flag = this.redisTemplate.opsForHash().hasKey(RedisConst.SECKILL_ORDERS_USERS, userId);
        if(flag){
            String orderId  = (String) this.redisTemplate.opsForHash().get(RedisConst.SECKILL_ORDERS_USERS, userId);
            //秒杀成功
            return Result.build(orderId, ResultCodeEnum.SECKILL_SUCCESS);
        }
        //检查状态位
        String status = (String) CacheHelper.get(skuId.toString());
        if(StringUtils.isEmpty(status) || "0".equals(status)){
            //已售罄
            return Result.build(null,ResultCodeEnum.SECKILL_ILLEGAL);
        }
        //默认值，去排队
        return Result.build(null,ResultCodeEnum.SECKILL_RUN);

    }

    @Transactional(rollbackFor = Exception.class)
    public void updateSeckill(Long skuId){

        String redisKey = RedisConst.SECKILL_STOCK_PREFIX+skuId;

        Long redisCount = redisTemplate.boundListOps(redisKey).size();

        SeckillGoods seckillGoods = this.getSeckillGoods(skuId);
        seckillGoods.setStockCount(redisCount.intValue());
        seckillGoodsMapper.updateById(seckillGoods);

        redisTemplate.boundHashOps(RedisConst.SECKILL_GOODS).put(seckillGoods.getSkuId().toString(),seckillGoods);

    }

}
